package org.oc.qaq.service.Impl;

import org.oc.qaq.constant.MessageConstant;
import org.oc.qaq.context.UserContext;
import org.oc.qaq.dto.TagDTO;
import org.oc.qaq.entity.FileEntity;
import org.oc.qaq.entity.FileTag;
import org.oc.qaq.entity.Tag;
import org.oc.qaq.exception.AlreadyExistException;
import org.oc.qaq.exception.FileNotFoundException;
import org.oc.qaq.exception.TagNotFoundException;
import org.oc.qaq.mapper.FileMapper;
import org.oc.qaq.mapper.TagMapper;
import org.oc.qaq.mapper.UserRoleMapper;
import org.oc.qaq.service.TagService;
import org.oc.qaq.vo.FileTagVO;
import org.oc.qaq.vo.TagVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class TagServiceImpl implements TagService {

    private final TagMapper tagMapper;
    private final FileMapper fileMapper;
    private final UserRoleMapper userRoleMapper;

    @Autowired
    public TagServiceImpl(TagMapper tagMapper, FileMapper fileMapper, UserRoleMapper userRoleMapper) {
        this.tagMapper = tagMapper;
        this.fileMapper = fileMapper;
        this.userRoleMapper = userRoleMapper;
    }

    @Override
    public List<Tag> getTags() {
        // 1. 获取当前登录用户的 ID
        String userId = UserContext.getCurrentId();

        // 2. 查询用户的角色 ID 列表
        List<Long> roleIds = userRoleMapper.findRoleIdsByUserId(userId);
        if (roleIds.isEmpty()) {
            return Collections.emptyList(); // 没有角色直接返回空列表
        }
        if (roleIds.contains(0L)) {
            // 如果当前用户有超级管理员角色，则直接返回所有标签
            return tagMapper.findAll();
        }

        // 3. 查询这些角色下的标签
        return tagMapper.findTagsByRoleIds(roleIds);
    }

    @Override
    @Transactional
    public void addTag(TagDTO tagDTO) {
        Tag tag = new Tag();
        tag.setName(tagDTO.getName());
        tag.setDescription(tagDTO.getDescription());
        tagMapper.insert(tag);

        String userId = UserContext.getCurrentId();

        List<Long> roleIds = userRoleMapper.findRoleIdsByUserId(userId);
        roleIds.forEach(roleId -> {
            tagMapper.insertTagRole(tag.getId(), roleId);
        });
    }

    @Override
    public void tagFile(String fileId, List<Long> tagIds) {
        FileEntity file = fileMapper.selectFileById(fileId);
        if (file == null) {
            throw new FileNotFoundException(MessageConstant.FILE_NOT_FOUND);
        }

        tagMapper.insertFileTags(tagIds.stream().map(tagId -> new FileTag(tagId, fileId)).toList());
    }

    @Override
    public void tagFile(String fileId, Long tagId) {
        FileEntity file = fileMapper.selectFileById(fileId);
        if (file == null) {
            throw new FileNotFoundException(MessageConstant.FILE_NOT_FOUND);
        }

        tagMapper.insertFileTag(fileId, tagId);
    }

    @Override
    public void updateTag(TagDTO tagDTO) {
        Tag tag = tagMapper.findById(tagDTO.getId());
        if (tag == null) {
            throw new TagNotFoundException("标签不存在");
        }
        BeanUtils.copyProperties(tagDTO, tag);
        tagMapper.update(tag);
    }

    @Override
    public Map<String, List<TagVO>> findTagsByFileIds(List<String> fileIds) {
        if (fileIds == null || fileIds.isEmpty()) {
            return Collections.emptyMap();
        }

        List<FileTagVO> fileTags = tagMapper.selectTagsByFileIds(fileIds);

        // 分组：fileId -> List<TagVO>
        return fileTags.stream()
                .collect(Collectors.groupingBy(
                        FileTagVO::getFileId,
                        Collectors.mapping(ft -> new TagVO(ft.getTagId(), ft.getTagName()),
                                Collectors.toList())
                ));
    }

    @Override
    public void removeDeleteTag(String id) {
        tagMapper.removeDeleteTag(id);
    }

    @Override
    @Transactional
    public void deleteBatch(List<Long> ids) {
        ids.forEach(id -> {
            if (isRelateFile(id)) {
                throw new AlreadyExistException(MessageConstant.TAG_RELATED);
            }
            tagMapper.delete(id);
        });
    }

    @Override
    public void deleteTagByFileId(String id) {
        tagMapper.deleteFileTagByFileId(id);
    }

    @Override
    public void delete(Long id) {
        if (isRelateFile(id)) {
            throw new AlreadyExistException(MessageConstant.TAG_RELATED);
        }
        tagMapper.deleteRoleTag(id);
        tagMapper.delete(id);
    }

    @Override
    public List<Tag> findTagsByUserId(String currUserId) {
        List<Long> roleIds = userRoleMapper.findRoleIdsByUserId(currUserId);
        if (roleIds.isEmpty()) {
            return Collections.emptyList();
        }
        if (roleIds.contains(0L)) {
            return tagMapper.findAll();
        }
        return tagMapper.findTagsByRoleIds(roleIds);
    }

    private Boolean isRelateFile(Long tagId) {
        List<FileTag> fileTags = tagMapper.selectFileTagsByTagId(tagId);
        return !fileTags.isEmpty();
    }
}
